package com.kandinfo.base.common.dto;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.validation.BindingResult;

import com.kandinfo.base.common.constant.ResultCode;
import com.kandinfo.base.common.enumeration.EErrorCode;
import com.kandinfo.base.common.exception.BaseException;
import com.kandinfo.base.common.exception.DisplayableError;
import com.kandinfo.base.common.util.AppConfigUtil;
import com.kandinfo.base.common.util.MessageUtil;


/**
* Class Name: ResultDtoFactory
* @author SC
*
*/
public final class ResultDtoFactory {

    private ResultDtoFactory() {
    };
    /**
     * 创建一个空的返回结果
     * @return
     */
    public static ResultDto createResult() {
    	return new ResultDto();
    }
    /**
     * 创建一个没有返回数据只有返回结果和消息的结果
     * @param code
     * @param message
     * @return
     */
    public static ResultDto createResult(String code, String message) {
    	return createResult(code, message, null);
    }
    /**
     * 创建一个有结果，有数据的返回消息
     * @param code
     * @param message
     * @param data
     * @return
     */
    public static ResultDto createResult(String code, String message, Object data){
        return createResult().setCode(code).setMessage(message).setData(data);
    }
    
    public static ResultDto toAck(String message) {
        return toAck(message, null);
    }
    
    public static ResultDto toAckNoCode(String message) {
        return toAckNoCode(message, null);
    }

    public static ResultDto toAck(String message, Object data) {
        return createResult().setCode(ResultCode.ACK).setMessage(message).setData(data);
    }
    
    public static ResultDto toAckNoCode(String message, Object data) {
        return createResult().setCode(null).setMessage(message).setData(data);
    }
    public static ResultDto toAckNomessage(Object data) {
        return createResult().setCode(ResultCode.ACK_NO_MESSAGE).setMessage(null).setData(data);
    }
    public static ResultDto toAckNomessage(String message, Object data) {
        return createResult().setCode(ResultCode.ACK_NO_MESSAGE).setMessage(message).setData(data);
    }
    
    public static ResultDto toRedirect(String url) {
        return createResult().setCode(ResultCode.REDIRECT).setMessage(null).setData(url);
    }

    public static ResultDto toRedirect(String url, String message) {
        return createResult().setCode(ResultCode.REDIRECT).setMessage(message).setData(url);
    }

    /**
     * Description: 在controller层直接返回错误消息，避免在controller中用该方法catch异常做处理
     * 
     * @param message
     * @return
     */
    public static ResultDto toNack(String message) {
        return toNack(message, null);
    }
    
    public static ResultDto toNackNoCode(String message) {
        return toNackNoCode(message, null);
    }

    /**
     * Description: 在controller层直接返回错误消息，避免在controller中用该方法catch异常做处理
     * 
     * @param error
     * @return
     */
    public static ResultDto toNack(DisplayableError error) {
        String message = "";
        if (error != null && StringUtils.isNotBlank(error.getErrorCode())) {
            message = MessageUtil.getMessage(error.getDisplayMsg(), error.getArgs());
        }
        return toNack(message, null);
    }

    /**
     * Description: 在controller层直接返回错误消息，避免在controller中用该方法catch异常做处理
     * 
     * @param message
     * @param data
     * @return
     */
    public static ResultDto toNack(String message, Object data) {
        return createResult().setCode(ResultCode.NACK).setMessage(message).setData(data);
    }
    
    public static ResultDto toNackNoCode(String message, Object data) {
        return createResult().setCode(null).setMessage(message).setData(data);
    }

    public static ResultDto toValidationError(String message, BindingResult br) {
        return createResult().setCode(ResultCode.VALIDATION_ERROR).setMessage(message).setData(br);
    }

    private static ResultDto toCommonError(String code, String message, String details) {
        ResultDto dto = new ResultDto();
        dto.setCode(ResultCode.COMMON_ERROR);
        StringBuilder text = new StringBuilder();
        if (StringUtils.isBlank(message)) {
            text.append(MessageUtil.getMessage(EErrorCode.COMM_INTERNAL_ERROR.getDisplayMsg())).append("[")
                    .append("时间：").append((new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new Date())).append("]");
        } else {
            text.append(message);
        }
        if (StringUtils.isNotBlank(code)) {
            text.append("(").append(code).append(")");
        }
        dto.setMessage(text.toString());
        if (!AppConfigUtil.isProdEnv()) {
            dto.setData(details);
        }
        return dto;
    }

    /**
     * Description: 异常的stacktrace和message将在非生产环境中显示出来
     * 
     * @param e
     * @return
     */
    public static ResultDto toCommonError(BaseException e) {
        String message = MessageUtil.getMessage(e.getError().getDisplayMsg());
        return toCommonError(e.getError().getErrorCode(), message, ExceptionUtils.getStackTrace(e));
    }

    /**
     * Description: 异常的stacktrace和message将在非生产环境中显示出来
     * 
     * @param e
     * @return
     */
    public static ResultDto toCommonError(Exception e) {
        return toCommonError(null, null, ExceptionUtils.getStackTrace(e));
    }

    /**
     * Description: 传入的msg将显示出来
     * 
     * @param message
     * @return
     */
    public static ResultDto toCommonError(String message) {
        return toCommonError(null, message, null);
    }

    public static ResultDto toBizError(String message, Exception e) {
        ResultDto dto = createResult().setCode(ResultCode.BUSINESS_ERROR).setMessage(message == null ? e.getMessage() : message);
        if (!AppConfigUtil.isProdEnv()) {
            dto.setData(ExceptionUtils.getStackTrace(e));
        }
        return dto;
    }
}
